import {
  BodyAttrs,
  BodyClasses,
  getCurrentHostname,
  getCurrentURL,
  HOSTNAME,
  logger,
  MODULE_CONFIG,
  SUPPORTED_PLATFORMS,
} from '../../../types/constants'
import { SYMBOLS } from '../../../types/interfaces'

/**
 * 平台工具类
 */
export class PlatformUtils {
  /**
   * 判断是否为移动端模式
   * @returns 是否为移动端模式
   */
  static isMobileMode(): boolean {
    return document.body.classList.contains(BodyClasses.IS_MOBILE)
  }

  /**
   * 检查域名是否支持当前脚本
   */
  static isSupportedPlatform(): boolean {
    return Object.values(SUPPORTED_PLATFORMS).includes(HOSTNAME)
  }

  /**
   * 标记当前版本是否支持当前平台
   */
  static markScriptSupportStatus(isSupported: boolean): void {
    document.body.setAttribute(BodyAttrs.IS_SUPPORTED, String(isSupported))
  }

  static isScriptSupported(): boolean {
    return !(document.body.getAttribute(BodyAttrs.IS_SUPPORTED) === 'false')
  }

  /**
   * 检查用户是否登录
   */
  static isLoggedIn(strict: boolean = false): boolean | undefined {
    const value = document.body.getAttribute(BodyAttrs.IS_LOGGED_IN)

    if (value === null) {
      return strict ? undefined : false
    }
    return value === 'true'
  }

  /**
   * 带平台检查的执行器（支持同步/异步回调）
   */
  static withPlatformCheck(
    callback: () => void | Promise<void>,
    options: { showMessage?: boolean } = { showMessage: true },
  ): boolean {
    if (!this.isSupportedPlatform()) {
      if (options.showMessage)
        logger.error(`${SYMBOLS.STATUS.ERROR} 脚本不支持当前平台：${HOSTNAME}`)
      return false
    }

    // 检查是否在 iframe 中运行
    if (this.isIframe()) {
      if (options.showMessage && !this.isProjectIframe())
        logger.warn(`${SYMBOLS.STATUS.WARNING} 跳过 iframe 中的脚本执行：${getCurrentURL()}`)
      return false
    }

    try {
      const result = callback()

      // 处理 Promise 返回值
      if (result instanceof Promise) {
        result.catch((e) => {
          logger.warn(`${SYMBOLS.STATUS.WARNING} 异步执行失败`, e)
          return false
        })
      }
    }
    catch (e) {
      logger.warn(`${SYMBOLS.STATUS.WARNING} 同步执行失败`, e)
      return false
    }

    return true
  }

  /**
   * 检查是否在 iframe 中运行
   */
  static isIframe(): boolean {
    return window.self !== window.top
  }

  /**
   * 检查是否为项目 iframe
   */
  static isProjectIframe(): boolean {
    // 检查当前窗口是否在 iframe 中
    if (!this.isIframe()) {
      return false
    }

    return this.isProjectElement($(window.frameElement as HTMLIFrameElement))
  }

  /**
   * 检查元素是否为受保护元素
   * @param $element 要检查的元素
   * @returns 如果元素是受保护元素则返回true，否则返回false
   */
  static isProjectElement($element: JQueryElement): boolean {
    return $element?.attr(BodyAttrs.PROJECT_MODULE) === 'true' || false
  }

  /**
   * 检查元素是否为项目弹窗元素
   * @param $element 要检查的元素
   * @returns 如果元素是项目弹窗元素则返回true，否则返回false
   */
  static isProjectAlertElement($element: JQueryElement): boolean {
    return $element?.attr(BodyAttrs.PROJECT_ALERT) === 'true' || false
  }

  /**
   * 标记为项目元素
   * @param $element
   */
  static markProjectElement($element: JQueryElement): void {
    // 检查元素是否已被保护
    if (this.isProjectElement($element))
      return

    $element?.attr(BodyAttrs.PROJECT_MODULE, 'true')
  }

  /**
   * 标记为项目弹窗元素
   * @param $element
   */
  static markProjectAlertElement($element: JQueryElement): void {
    // 检查元素是否已被保护
    if (this.isProjectAlertElement($element))
      return

    $element?.attr(BodyAttrs.PROJECT_ALERT, 'true')
  }

  /**
   * 标记元素
   */
  static markElement($element: JQuery<HTMLElement>, className: string): JQuery<HTMLElement> {
    return $element
      .not(`[${BodyAttrs.MARK_ELEMENT}="true"]`)
      .addClass(className)
      .attr(BodyAttrs.MARK_ELEMENT, 'true')
  }

  /**
   * 获取滚动条偏移量
   * @param isNegative 是否为负数
   * @returns 滚动条偏移量
   */
  static getScrollbarOffset(isNegative: boolean = true) {
    return `calc(${isNegative ? '-1 * ' : ''}var(${MODULE_CONFIG.PAGE.body.styleVar.scrollbarOffset}, 0px) / 2)`
  }

  /**
   * 获取受保护的属性选择器值（基于域名生成动态属性名）
   * @returns 返回受保护的属性选择器
   */
  static getProtectedAttr(): string {
    const domainHash = getCurrentHostname()
      .split('')
      .reduce((a, b) => {
        a = ((a << 5) - a) + b.charCodeAt(0)
        return a & a
      }, 0)
      .toString(16)
      .substring(0, 4)
    return `data-${domainHash}="1"`
  }

  /**
   * 强制重绘元素
   * @param element 要重绘的元素
   */
  static forceRepaid(element: HTMLElement): void {
    // 方法1：触发回流
    void element.offsetHeight

    // 方法2：使用requestAnimationFrame确保在下一帧执行
    requestAnimationFrame(() => {
      element.style.transform = 'translateZ(0)' //  启用 GPU 加速层
      requestAnimationFrame(() => {
        element.style.transform = ''
      })
    })
  }
}
